<!DOCTYPE html>












  


<html class="theme-next pisces use-motion" lang="zh-CN">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">






















<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css?v=4.7.0">

<link rel="stylesheet" href="/css/main.css?v=7.1.2">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=7.1.2">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=7.1.2">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=7.1.2">


  <link rel="mask-icon" href="/images/logo.svg?v=7.1.2" color="#222">







<script id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    version: '7.1.2',
    sidebar: {"position":"left","display":"post","offset":12,"onmobile":false,"dimmer":false},
    back2top: true,
    back2top_sidebar: false,
    fancybox: false,
    fastclick: false,
    lazyload: false,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>


  




  <meta name="description" content="一个程序同时执行多个任务。通常，每一个任务称为一个线程（ thread ), 它是线程控制的简称。可以同时运行一个以上线程的程序称为多线程程序（multithreaded)。">
<meta name="keywords" content="多线程">
<meta property="og:type" content="article">
<meta property="og:title" content="多线程基础">
<meta property="og:url" content="https://lzz001.gitee.io/2019/11/14/多线程基础/index.html">
<meta property="og:site_name" content="小智的博客">
<meta property="og:description" content="一个程序同时执行多个任务。通常，每一个任务称为一个线程（ thread ), 它是线程控制的简称。可以同时运行一个以上线程的程序称为多线程程序（multithreaded)。">
<meta property="og:locale" content="zh-CN">
<meta property="og:updated_time" content="2019-11-18T15:18:01.477Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="多线程基础">
<meta name="twitter:description" content="一个程序同时执行多个任务。通常，每一个任务称为一个线程（ thread ), 它是线程控制的简称。可以同时运行一个以上线程的程序称为多线程程序（multithreaded)。">





  
  
  <link rel="canonical" href="https://lzz001.gitee.io/2019/11/14/多线程基础/">



<script id="page.configurations">
  CONFIG.page = {
    sidebar: "",
  };
</script>

  <title>多线程基础 | 小智的博客</title>
  






  <script>
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?297412c3c8589eb0dc190e2d81f12097";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>







  <noscript>
  <style>
  .use-motion .motion-element,
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-title { opacity: initial; }

  .use-motion .logo,
  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>
	<a href="https://github.com/zengzhiLai" target="_blank" class="github-corner" aria-label="View source on GitHub">
		<svg width="100" height="100" viewbox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true">
			<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"/>
			<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"/><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"/>
		</svg>
	</a>
	<style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
	
    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">小智的博客</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
    
      
        <p class="site-subtitle">慢即是快</p>
      
    
    
  </div>

  <div class="site-nav-toggle">
    <button aria-label="切换导航栏">
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>



<nav class="site-nav">
  
    <ul id="menu" class="menu">
      
        
        
        
          
          <li class="menu-item menu-item-home">

    
    
      
    

    

    <a href="/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i> <br>首页</a>

  </li>
        
        
        
          
          <li class="menu-item menu-item-about">

    
    
      
    

    

    <a href="/about/" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i> <br>关于</a>

  </li>
        
        
        
          
          <li class="menu-item menu-item-tags">

    
    
      
    

    

    <a href="/tags/" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i> <br>标签</a>

  </li>
        
        
        
          
          <li class="menu-item menu-item-categories">

    
    
      
    

    

    <a href="/categories/" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i> <br>分类</a>

  </li>
        
        
        
          
          <li class="menu-item menu-item-archives">

    
    
      
    

    

    <a href="/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i> <br>归档</a>

  </li>
        
        
        
          
          <li class="menu-item menu-item-commonweal">

    
    
      
    

    

    <a href="/404/" rel="section"><i class="menu-item-icon fa fa-fw fa-heartbeat"></i> <br>公益 404</a>

  </li>

      
      
    </ul>
  

  

  
</nav>



  



</div>
    </header>

    


    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          
            

          
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://lzz001.gitee.io/2019/11/14/多线程基础/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="小智">
      <meta itemprop="description" content="Java,Linux,Mysql">
      <meta itemprop="image" content="/images/zhi.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="小智的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">多线程基础

              
            
          </h1>
        

        <div class="post-meta">

          
          
          

          
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2019-11-14 21:45:56" itemprop="dateCreated datePublished" datetime="2019-11-14T21:45:56+08:00">2019-11-14</time>
            </span>
          

          
            

            
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">更新于</span>
                
                <time title="修改时间：2019-11-18 23:18:01" itemprop="dateModified" datetime="2019-11-18T23:18:01+08:00">2019-11-18</time>
              </span>
            
          

          
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/Java/" itemprop="url" rel="index"><span itemprop="name">Java</span></a></span>

                
                
              
            </span>
          

          
            
            
          

          
          

          
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
                 阅读次数： 
                <span class="busuanzi-value" id="busuanzi_value_page_pv"></span>
              </span>
            </span>
          

          <br>
          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <blockquote>
<p>一个程序同时执行多个任务。通常，每一个任务称为一个<strong>线程</strong>（ thread ), 它是线程控制的简称。可以同时运行一个以上线程的程序称为<strong>多线程程序</strong>（multithreaded)。 </p>
</blockquote>
<a id="more"></a>
<h2 id="进程与线程的区别"><a href="#进程与线程的区别" class="headerlink" title="进程与线程的区别"></a>进程与线程的区别</h2><table>
<thead>
<tr>
<th>区别</th>
<th>进程</th>
<th>线程</th>
</tr>
</thead>
<tbody><tr>
<td>根本区别</td>
<td>作为资源分配的单位</td>
<td>调度和执行的单位</td>
</tr>
<tr>
<td>开销</td>
<td>每个进程都有独立的代码和数据空间（进程上下文），进程间的切换会有较大的开销</td>
<td>线程可以看成是轻量级的进程，同一类线程共享代码和数据空间，每一个线程有独立的运行栈和程序计数器（PC），线程切换的开销小</td>
</tr>
<tr>
<td>所处环境</td>
<td>在操作系统中能同时运行多个任务（程序）</td>
<td>在同一个应用程序中有多个顺序流同时执行</td>
</tr>
<tr>
<td>分配内存</td>
<td>系统在运行时会为每个进程分配不同的内存区域</td>
<td>除了CPU之外，不会为线程分配内存（线程所使用的资源是它所属进程的资源），线程组只能共享资源</td>
</tr>
<tr>
<td>包含关系</td>
<td>没有线程的进程是可以被看作单线程的，如果一个进程内拥有多个线程，则执行过程不是一条线的，而是多条线（线程）共同完成的</td>
<td>线程是进程的一部分，所以线程有的时候被称为是轻权进程或者轻量级进程</td>
</tr>
</tbody></table>
<h2 id="Java实现多线程的方法"><a href="#Java实现多线程的方法" class="headerlink" title="Java实现多线程的方法"></a>Java实现多线程的方法</h2><h3 id="1-继承Thread类"><a href="#1-继承Thread类" class="headerlink" title="1. 继承Thread类"></a>1. 继承Thread类</h3><ul>
<li>Java中负责多线程功能的类是 <code>java.lang.Thread</code></li>
<li>通过创建 Thread 的实例来创建新的线程</li>
<li>每个线程都是通过特定的Thread对象所对应的方法<strong>run()</strong>（线程体）来完成操作</li>
<li>调用 Thread 类的<strong>start()</strong>方法来启动一个线程</li>
<li>缺点：如果类已经继承了一个类（如小程序必须继承自 Applet 类），则无法再继承 Thread 类</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestThread</span> <span class="keyword">extends</span> <span class="title">Thread</span></span>&#123; <span class="comment">// 继承Thread类</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>; i&lt; <span class="number">5</span>; i++)&#123;</span><br><span class="line">            System.out.println(<span class="keyword">this</span>.getName() + <span class="string">":"</span> + i); <span class="comment">// getName() 返回线程名称</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">    	TestThread thread1 = <span class="keyword">new</span> TestThread(); <span class="comment">// 创建线程对象</span></span><br><span class="line">        thread1.start(); <span class="comment">// 启动线程</span></span><br><span class="line">        TestThread thread2 = <span class="keyword">new</span> TestThread();</span><br><span class="line">        thread2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*输出</span></span><br><span class="line"><span class="comment">Thread-0:0</span></span><br><span class="line"><span class="comment">Thread-0:1</span></span><br><span class="line"><span class="comment">Thread-0:2</span></span><br><span class="line"><span class="comment">Thread-0:3</span></span><br><span class="line"><span class="comment">Thread-0:4</span></span><br><span class="line"><span class="comment">Thread-1:0</span></span><br><span class="line"><span class="comment">Thread-1:1</span></span><br><span class="line"><span class="comment">Thread-1:2</span></span><br><span class="line"><span class="comment">Thread-1:3</span></span><br><span class="line"><span class="comment">Thread-1:4</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<h3 id="2-实现Runnable接口"><a href="#2-实现Runnable接口" class="headerlink" title="2. 实现Runnable接口"></a>2. 实现Runnable接口</h3><ul>
<li>实现 Runnable 接口的同时可以继承某个类，此方法更通用一些</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestThread2</span> <span class="keyword">implements</span> <span class="title">Runnable</span></span>&#123; <span class="comment">// 实现 Runnable 接口</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>; i &lt; <span class="number">5</span>; i++)&#123;</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">":"</span> + i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        <span class="comment">// 创建线程对象，将实现了Runnable接口的对象作为参数传入</span></span><br><span class="line">        Thread thread1  = <span class="keyword">new</span> Thread(<span class="keyword">new</span> TestThread2());</span><br><span class="line">        thread1.start();</span><br><span class="line">        Thread thread2  = <span class="keyword">new</span> Thread(<span class="keyword">new</span> TestThread2());</span><br><span class="line">        thread2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 输出与继承Thread的类似</span></span><br></pre></td></tr></table></figure>

<h2 id="线程的状态"><a href="#线程的状态" class="headerlink" title="线程的状态"></a>线程的状态</h2><p>​    线程有以下5中状态（ps:《Java核心技术I 》中是6种）</p>
<p>​    要确定一个线程的当前状态，可调用 getState 方法</p>
<ul>
<li><strong>新生状态（NEW）</strong><br>用<strong>new</strong>关键字（如<strong>new Thread（r）</strong>）建立一个线程对象后，该线程就处于新生状态</li>
<li><strong>就绪状态（Runnable）</strong><br>具备运行条件，但没被分配到CPU，处于“线程就绪状态”，<strong>等待系统为其分配CPU</strong>。就绪状态并不是执行状态，当系统选定一个等待执行Thread对象后，它就会进入执行状态，一旦获得CPU，线程就进入运行状态并自动调用自己的run方法。<br>导致线程进入就绪状态的4个原因：<ul>
<li>新建线程：调用 <code>start()</code> 方法，进入就绪状态</li>
<li>阻塞线程：阻塞解除，进入就绪状态</li>
<li>运行线程：调用 <code>yield()</code>方法，直接进入就绪状态</li>
<li>运行线程：JVM将CPU资源从本线程切换到其它线程</li>
</ul>
<strong>在任何给定时刻，一个可运行的线程可能正在运行也可能没有运行</strong> </li>
<li><strong>运行状态（Running）</strong><br>在运行状态的线程执行自己run方法中的代码，直到调用其他方法而终止或等待某资源而阻塞或完成任务而死亡。如果在给定的时间片内没有执行结束，就会被系统给换下来回到就绪状态。也可能由于某些“导致阻塞的事件”而进入阻塞状态。</li>
<li><strong>阻塞状态（Blocked）</strong><br>暂停一个线程的执行以等待某个条件发生（如某资源就绪）。<br>导致阻塞的4种原因：<ul>
<li>执行 <code>sleep(int millsecond)</code> 方法，使当前线程休眠，进入阻塞状态。当到了指定的时间后，线程进入就绪状态。</li>
<li>执行 <code>wait()</code> 方法，使当前线程进入阻塞状态。当使用 <code>notify()</code> 方法唤醒该线程后，进入就绪状态</li>
<li>线程运行时，某个操作进入阻塞状态，比如执行IO流操作( <code>read()/write()</code> 方法本身就是阻塞的方法)。只有当引起该操作阻塞的原因消失后，线程进入就绪状态</li>
<li><code>join()</code>线程联合: 当某个线程等待另一个线程执行结束后，才能继续执行时，使用join()方法</li>
</ul>
</li>
<li><strong>死亡状态（Terminated）</strong><br>死亡状态是线程生命周期中的最后一个阶段。<br>线程死亡的两个原因：<ul>
<li>正常运行的线程完成了它 run() 方法内的全部工作</li>
<li>线程被强制终止，如通过执行 stop() 或 destroy() 方法（这两个方法已过时）来终止一个线程<br>当一个线程进入死亡状态以后，就不能再回到其它状态了</li>
</ul>
</li>
</ul>
<h3 id="终止线程的典型方式"><a href="#终止线程的典型方式" class="headerlink" title="终止线程的典型方式"></a>终止线程的典型方式</h3><p>设置一个 boolean型的终止变量，当它为 false 时，终止线程的运行</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestThreadCiycle</span> <span class="keyword">implements</span> <span class="title">Runnable</span> </span>&#123;</span><br><span class="line">    String name;</span><br><span class="line">    <span class="keyword">boolean</span> live = <span class="keyword">true</span>;<span class="comment">// 标记变量，表示线程是否可中止；</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">TestThreadCiycle</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>();</span><br><span class="line">        <span class="keyword">this</span>.name = name;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line">        <span class="comment">//当live的值是true时，继续线程体；false则结束循环，继而终止线程体；</span></span><br><span class="line">        <span class="keyword">while</span> (live) &#123;</span><br><span class="line">            System.out.println(name + (i++));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">terminate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        live = <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        TestThreadCiycle ttc = <span class="keyword">new</span> TestThreadCiycle(<span class="string">"线程A:"</span>);</span><br><span class="line">        Thread t1 = <span class="keyword">new</span> Thread(ttc);<span class="comment">// 新生状态</span></span><br><span class="line">        t1.start();<span class="comment">// 就绪状态</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span>(i == <span class="number">88</span>)&#123;</span><br><span class="line">                ttc.terminate();</span><br><span class="line">        		System.out.println(<span class="string">"ttc stop!"</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            System.out.println(<span class="string">"主线程"</span> + i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="暂停线程sleep-yield"><a href="#暂停线程sleep-yield" class="headerlink" title="暂停线程sleep/yield"></a>暂停线程sleep/yield</h3><ul>
<li><code>sleep()</code>：可以让正在运行的线程<strong>进入阻塞状态</strong>，直到休眠时间满了，进入就绪状态</li>
<li><code>yield()</code>：可以让正在运行的线程<strong>直接进入就绪状态</strong>，让出CPU的使用权</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestThreadState</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        StateThread thread1 = <span class="keyword">new</span> StateThread();</span><br><span class="line">        thread1.start();</span><br><span class="line">        StateThread thread2 = <span class="keyword">new</span> StateThread();</span><br><span class="line">        thread2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//使用继承方式实现多线程</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">StateThread</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 方法一：sleep()</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            System.out.println(<span class="keyword">this</span>.getName() + <span class="string">":"</span> + i);</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">2000</span>);<span class="comment">//调用线程的sleep()方法,睡眠2秒</span></span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//方法二：yield()</span></span><br><span class="line">    <span class="comment">/* </span></span><br><span class="line"><span class="comment">    public void run() &#123;</span></span><br><span class="line"><span class="comment">        for (int i = 0; i &lt; 100; i++) &#123;</span></span><br><span class="line"><span class="comment">            System.out.println(this.getName() + ":" + i);</span></span><br><span class="line"><span class="comment">            Thread.yield(); //调用线程的yield()方法；</span></span><br><span class="line"><span class="comment">        &#125;</span></span><br><span class="line"><span class="comment">    &#125;</span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="线程的联合-join"><a href="#线程的联合-join" class="headerlink" title="线程的联合 join()"></a>线程的联合 join()</h3><p>线程A在运行期间，可以调用线程B的<code>join()</code>方法，让线程B和线程A联合。这样，线程A就必须等待线程B执行完毕后，才能继续执行。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> thread;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestThreadState</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Thread a = <span class="keyword">new</span> Thread(<span class="keyword">new</span> AThread());</span><br><span class="line">        a.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * A线程</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">AThread</span> <span class="keyword">implements</span> <span class="title">Runnable</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        Thread b = <span class="keyword">new</span> Thread(<span class="keyword">new</span> BThread());</span><br><span class="line">        b.start();</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            b.join();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="comment">// 结束JVM 如果是0则表示正常结束；如果是非0则表示非正常结束</span></span><br><span class="line">            System.exit(<span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">"A线程 联合 B线程 成功"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * B线程</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BThread</span> <span class="keyword">implements</span> <span class="title">Runnable</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= <span class="number">10</span>; i++) &#123;</span><br><span class="line">                System.out.println(<span class="string">"第"</span> + i + <span class="string">"分钟"</span>);</span><br><span class="line">                Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(<span class="string">"B线程 结束"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="获取线程基本信息的方法"><a href="#获取线程基本信息的方法" class="headerlink" title="获取线程基本信息的方法"></a>获取线程基本信息的方法</h2><table>
<thead>
<tr>
<th>方法</th>
<th>功能</th>
</tr>
</thead>
<tbody><tr>
<td><code>isAlive()</code></td>
<td>判断线程是否还未终止</td>
</tr>
<tr>
<td><code>getPriority()</code></td>
<td>获取线程的优先级数值</td>
</tr>
<tr>
<td><code>setPriority()</code></td>
<td>设置线程的<strong>优先级</strong>数值</td>
</tr>
<tr>
<td><code>setName()</code></td>
<td>设置线程名称</td>
</tr>
<tr>
<td><code>getName()</code></td>
<td>获取线程名称</td>
</tr>
<tr>
<td><code>currentThread()</code></td>
<td>获取当前正在运行的线程对象，即取得自己本身</td>
</tr>
</tbody></table>
<h2 id="线程的优先级"><a href="#线程的优先级" class="headerlink" title="线程的优先级"></a>线程的优先级</h2><ul>
<li>线程的优先级用数字表示，范围是 1 ~ 10，一个线程的缺省优先级是 5</li>
<li>优先级低只是意味着获得调度的概率低。<strong>并不是绝对</strong> 先调用优先级高的线程 后调用优先级低的线程</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestThread</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Thread t1 = <span class="keyword">new</span> Thread(<span class="keyword">new</span> MyThread(), <span class="string">"t1"</span>);</span><br><span class="line">        Thread t2 = <span class="keyword">new</span> Thread(<span class="keyword">new</span> MyThread(), <span class="string">"t2"</span>);</span><br><span class="line">        t1.setPriority(<span class="number">1</span>);</span><br><span class="line">        t2.setPriority(<span class="number">10</span>);</span><br><span class="line">        t1.start();</span><br><span class="line">        t2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyThread</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">": "</span> + i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="线程同步"><a href="#线程同步" class="headerlink" title="线程同步"></a>线程同步</h2><ul>
<li>多个线程访问同一个对象，且某些线程还想修改这个对象。此时，需要用到“线程同步”。</li>
<li>线程同步其实是一个等待机制，多个需要同时访问此对象的线程进入这个对象的等待池形成队列，等待前面的线程使用完毕后，下一个线程再使用</li>
</ul>
<h3 id="线程不同步——银行取钱"><a href="#线程不同步——银行取钱" class="headerlink" title="线程不同步——银行取钱"></a>线程不同步——银行取钱</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> thread;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestSync</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        Account a = <span class="keyword">new</span> Account(<span class="string">"A"</span>, <span class="number">100</span>);</span><br><span class="line">        Drawing drawing1 = <span class="keyword">new</span> Drawing(a, <span class="number">80</span>, <span class="string">"我取钱"</span>);</span><br><span class="line">        Drawing drawing2 = <span class="keyword">new</span> Drawing(a, <span class="number">80</span>, <span class="string">"她取钱"</span>);</span><br><span class="line">        drawing1.start();</span><br><span class="line">        drawing2.start();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 银行账户</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Account</span> </span>&#123;</span><br><span class="line">        String name; <span class="comment">// 账户名称</span></span><br><span class="line">        <span class="keyword">int</span> money; <span class="comment">// 金额</span></span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">Account</span><span class="params">(String name, <span class="keyword">int</span> money)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">this</span>.name = name;</span><br><span class="line">            <span class="keyword">this</span>.money = money;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 模拟提款操作</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Drawing</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;</span><br><span class="line">        Account account; <span class="comment">// 提款的账户</span></span><br><span class="line">        <span class="keyword">int</span> drawingNum; <span class="comment">// 提取的金额</span></span><br><span class="line">        <span class="keyword">int</span> expenseTotal; <span class="comment">// 总共提取的金额</span></span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">Drawing</span><span class="params">(Account account, <span class="keyword">int</span> drawingNum, String name)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">super</span>(name);</span><br><span class="line">            <span class="keyword">this</span>.account = account;</span><br><span class="line">            <span class="keyword">this</span>.drawingNum = drawingNum;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            <span class="keyword">if</span> (account.money - drawingNum &lt; <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                Thread.sleep(<span class="number">1000</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            account.money -= drawingNum;</span><br><span class="line">            expenseTotal += drawingNum;</span><br><span class="line">            System.out.println(<span class="keyword">this</span>.getName() + <span class="string">"--账户余额："</span> + account.money);</span><br><span class="line">            System.out.println(<span class="keyword">this</span>.getName() + <span class="string">"--共取了："</span> + expenseTotal);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">她取钱--账户余额：20</span></span><br><span class="line"><span class="comment">她取钱--共取了：80</span></span><br><span class="line"><span class="comment">我取钱--账户余额：-60</span></span><br><span class="line"><span class="comment">我取钱--共取了：80</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>

<h3 id="实现线程同步——银行取钱"><a href="#实现线程同步——银行取钱" class="headerlink" title="实现线程同步——银行取钱"></a>实现线程同步——银行取钱</h3><ul>
<li><p><strong>synchronized 方法</strong></p>
<ul>
<li>synchronized 方法控制对“<strong>对象的类成员变量</strong>”的访问</li>
<li>每个对象对应一把锁，每个 synchronized 方法都必须获得调用该方法的对象的锁方能执行，否则所属线程阻塞</li>
<li>方法一旦执行，就独占该锁，直到从该方法返回时才将锁释放，此后被阻塞的线程方能获得该锁，重新进入可执行状态</li>
<li>缺点：若将一个大的方法声明为synchronized 将会大大影响效率。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title">method</span><span class="params">(<span class="keyword">int</span> args)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="comment">// method body</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>synchronized 块</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">synchronized</span>(syncObject)&#123;</span><br><span class="line">    <span class="comment">// 允许访问控制的代码</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> thread;</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestSync</span> </span>&#123;</span><br><span class="line">      <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">          Account a = <span class="keyword">new</span> Account(<span class="string">"A"</span>, <span class="number">100</span>);</span><br><span class="line">          Drawing drawing1 = <span class="keyword">new</span> Drawing(a, <span class="number">80</span>, <span class="string">"我取钱"</span>);</span><br><span class="line">          Drawing drawing2 = <span class="keyword">new</span> Drawing(a, <span class="number">80</span>, <span class="string">"她取钱"</span>);</span><br><span class="line">          drawing1.start();</span><br><span class="line">          drawing2.start();</span><br><span class="line">      &#125;</span><br><span class="line">  </span><br><span class="line">      <span class="comment">/**</span></span><br><span class="line"><span class="comment">       * 银行账户</span></span><br><span class="line"><span class="comment">       */</span></span><br><span class="line">      <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Account</span> </span>&#123;</span><br><span class="line">          String name; <span class="comment">// 账户名称</span></span><br><span class="line">          <span class="keyword">int</span> money; <span class="comment">// 金额</span></span><br><span class="line">  </span><br><span class="line">          <span class="function"><span class="keyword">public</span> <span class="title">Account</span><span class="params">(String name, <span class="keyword">int</span> money)</span> </span>&#123;</span><br><span class="line">              <span class="keyword">this</span>.name = name;</span><br><span class="line">              <span class="keyword">this</span>.money = money;</span><br><span class="line">          &#125;</span><br><span class="line">      &#125;</span><br><span class="line">  </span><br><span class="line">      <span class="comment">/**</span></span><br><span class="line"><span class="comment">       * 模拟提款操作</span></span><br><span class="line"><span class="comment">       */</span></span><br><span class="line">      <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Drawing</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;</span><br><span class="line">          Account account; <span class="comment">// 提款的账户</span></span><br><span class="line">          <span class="keyword">int</span> drawingNum; <span class="comment">// 提取的金额</span></span><br><span class="line">          <span class="keyword">int</span> expenseTotal; <span class="comment">// 总共提取的金额</span></span><br><span class="line">  </span><br><span class="line">          <span class="function"><span class="keyword">public</span> <span class="title">Drawing</span><span class="params">(Account account, <span class="keyword">int</span> drawingNum, String name)</span> </span>&#123;</span><br><span class="line">              <span class="keyword">super</span>(name);</span><br><span class="line">              <span class="keyword">this</span>.account = account;</span><br><span class="line">              <span class="keyword">this</span>.drawingNum = drawingNum;</span><br><span class="line">          &#125;</span><br><span class="line">  </span><br><span class="line">          <span class="meta">@Override</span></span><br><span class="line">          <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">              draw();</span><br><span class="line">          &#125;</span><br><span class="line">  </span><br><span class="line">          <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">draw</span><span class="params">()</span> </span>&#123;</span><br><span class="line">              <span class="comment">// 可提高性能</span></span><br><span class="line">              <span class="keyword">if</span>(account.money&lt;=<span class="number">0</span>)&#123;</span><br><span class="line">                  <span class="keyword">return</span>;</span><br><span class="line">              &#125;</span><br><span class="line">              <span class="keyword">synchronized</span> (account) &#123; <span class="comment">// 线程需获得account对象的“锁”才有资格运行同步块中的代码</span></span><br><span class="line">                  <span class="keyword">if</span> (account.money - drawingNum &lt; <span class="number">0</span>) &#123;</span><br><span class="line">                      System.out.println(<span class="keyword">this</span>.getName() + <span class="string">"-- 余额不足！"</span>);</span><br><span class="line">                      <span class="keyword">return</span>;</span><br><span class="line">                  &#125;</span><br><span class="line">                  <span class="keyword">try</span> &#123;</span><br><span class="line">                      Thread.sleep(<span class="number">1000</span>); <span class="comment">// 判断完后阻塞。其他线程开始运行。</span></span><br><span class="line">                  &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                      e.printStackTrace();</span><br><span class="line">                  &#125;</span><br><span class="line">                  account.money -= drawingNum;</span><br><span class="line">                  expenseTotal += drawingNum;</span><br><span class="line">              &#125;</span><br><span class="line">              System.out.println(<span class="keyword">this</span>.getName() + <span class="string">"--账户余额："</span> + account.money);</span><br><span class="line">              System.out.println(<span class="keyword">this</span>.getName() + <span class="string">"--总共取了："</span> + expenseTotal);</span><br><span class="line">          &#125;</span><br><span class="line">      &#125;</span><br><span class="line">  </span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">/*</span></span><br><span class="line"><span class="comment">  我取钱--账户余额：20</span></span><br><span class="line"><span class="comment">  她取钱-- 余额不足！</span></span><br><span class="line"><span class="comment">  我取钱--总共取了：80</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure>




</li>
</ul>
<h2 id="死锁"><a href="#死锁" class="headerlink" title="死锁"></a>死锁</h2><ul>
<li>多个线程同时被阻塞，它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞，因此程序不可能正常终止。</li>
<li>死锁产生的四个必要条件：<ul>
<li>互斥使用。当资源被一个线程使用（占有）时，别的线程不能使用</li>
<li>不可抢占。资源请求者不能强制从资源占有者手中夺取资源，资源只能由资源占有者主动释放</li>
<li>请求和保持。当资源请求者在请求其它资源的同时保持对原有资源的占有</li>
<li>循环等待。存在一个等待队列：P1占有P2的资源，P2占有P3的 资源；P3占有P1的资源，形成一个等待环路</li>
</ul>
</li>
<li>打破其中任一条件便可解决死锁问题</li>
</ul>
<h3 id="死锁问题"><a href="#死锁问题" class="headerlink" title="死锁问题"></a>死锁问题</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* 两个资源obj1和obj2</span></span><br><span class="line"><span class="comment">* A锁住obj1,B锁住obj2，然后A再想锁住obj2,B再想锁住obj1,</span></span><br><span class="line"><span class="comment">* 但此时这两个资源都分别被A或B锁住了，所以就产生了死锁</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LockTest</span> </span>&#123;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">static</span> String obj1 = <span class="string">"obj1"</span>;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">static</span> String obj2 = <span class="string">"obj2"</span>;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">      <span class="keyword">new</span> Thread(<span class="keyword">new</span> LockA()).start();</span><br><span class="line">      <span class="keyword">new</span> Thread(<span class="keyword">new</span> LockB()).start();</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LockA</span> <span class="keyword">implements</span> <span class="title">Runnable</span></span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">         System.out.println(Thread.currentThread().getName() + <span class="string">" LockA 开始执行"</span>);</span><br><span class="line">         <span class="keyword">while</span>(<span class="keyword">true</span>)&#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (LockTest.obj1) &#123;</span><br><span class="line">               System.out.println(Thread.currentThread().getName() + <span class="string">" LockA 锁住 obj1"</span>);</span><br><span class="line">               Thread.sleep(<span class="number">3000</span>); <span class="comment">// 此处等待是给B能锁住机会</span></span><br><span class="line">               <span class="keyword">synchronized</span> (LockTest.obj2) &#123;</span><br><span class="line">                  System.out.println(Thread.currentThread().getName() + <span class="string">" LockA 锁住 obj2"</span>);</span><br><span class="line">                  Thread.sleep(<span class="number">60</span> * <span class="number">1000</span>); <span class="comment">// 为测试，占用了就不放</span></span><br><span class="line">               &#125;</span><br><span class="line">            &#125;</span><br><span class="line">         &#125;</span><br><span class="line">      &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">         e.printStackTrace();</span><br><span class="line">      &#125;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LockB</span> <span class="keyword">implements</span> <span class="title">Runnable</span></span>&#123;</span><br><span class="line">   <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">         System.out.println(Thread.currentThread().getName() + <span class="string">" LockB 开始执行"</span>);</span><br><span class="line">         <span class="keyword">while</span>(<span class="keyword">true</span>)&#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (LockTest.obj2) &#123;</span><br><span class="line">               System.out.println(Thread.currentThread().getName() + <span class="string">" LockB 锁住 obj2"</span>);</span><br><span class="line">               Thread.sleep(<span class="number">3000</span>); <span class="comment">// 此处等待是给A能锁住机会</span></span><br><span class="line">               <span class="keyword">synchronized</span> (LockTest.obj1) &#123;</span><br><span class="line">                  System.out.println(Thread.currentThread().getName() + <span class="string">" LockB 锁住 obj1"</span>);</span><br><span class="line">                  Thread.sleep(<span class="number">60</span> * <span class="number">1000</span>); <span class="comment">// 为测试，占用了就不放</span></span><br><span class="line">               &#125;</span><br><span class="line">            &#125;</span><br><span class="line">         &#125;</span><br><span class="line">      &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">         e.printStackTrace();</span><br><span class="line">      &#125;</span><br><span class="line">   &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="解决死锁"><a href="#解决死锁" class="headerlink" title="解决死锁"></a>解决死锁</h3><p>死锁是由于“同步块需要同时持有多个对象锁造成”的，所以同一个代码块，不要同时持有两个对象锁就可以解决了</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LockTest</span> </span>&#123;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">static</span> String obj1 = <span class="string">"obj1"</span>;</span><br><span class="line">	<span class="keyword">public</span> <span class="keyword">static</span> String obj2 = <span class="string">"obj2"</span>;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">		<span class="keyword">new</span> Thread(<span class="keyword">new</span> LockA()).start();</span><br><span class="line">		<span class="keyword">new</span> Thread(<span class="keyword">new</span> LockB()).start();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LockA</span> <span class="keyword">implements</span> <span class="title">Runnable</span></span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">try</span> &#123;</span><br><span class="line">			System.out.println(Thread.currentThread().getName() + <span class="string">" LockA 开始执行"</span>);</span><br><span class="line">			<span class="keyword">while</span>(<span class="keyword">true</span>)&#123;</span><br><span class="line">				<span class="keyword">synchronized</span> (LockTest.obj1) &#123;</span><br><span class="line">					System.out.println(Thread.currentThread().getName() + <span class="string">" LockA 锁住 obj1"</span>);</span><br><span class="line">					Thread.sleep(<span class="number">3000</span>); <span class="comment">// 此处等待是给B能锁住机会</span></span><br><span class="line">				&#125;</span><br><span class="line">				<span class="keyword">synchronized</span> (LockTest.obj2) &#123;</span><br><span class="line">					System.out.println(Thread.currentThread().getName() + <span class="string">" LockA 锁住 obj2"</span>);</span><br><span class="line">					Thread.sleep(<span class="number">60</span> * <span class="number">1000</span>); <span class="comment">// 为测试，占用了就不放</span></span><br><span class="line">				&#125;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">			e.printStackTrace();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LockB</span> <span class="keyword">implements</span> <span class="title">Runnable</span></span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">		<span class="keyword">try</span> &#123;</span><br><span class="line">			System.out.println(Thread.currentThread().getName() + <span class="string">" LockB 开始执行"</span>);</span><br><span class="line">			<span class="keyword">while</span>(<span class="keyword">true</span>)&#123;</span><br><span class="line">				<span class="keyword">synchronized</span> (LockTest.obj2) &#123;</span><br><span class="line">					System.out.println(Thread.currentThread().getName() + <span class="string">" LockB 锁住 obj2"</span>);</span><br><span class="line">					Thread.sleep(<span class="number">3000</span>); <span class="comment">// 此处等待是给A能锁住机会</span></span><br><span class="line">				&#125;</span><br><span class="line">				<span class="keyword">synchronized</span> (LockTest.obj1) &#123;</span><br><span class="line">					System.out.println(Thread.currentThread().getName() + <span class="string">" LockB 锁住 obj1"</span>);</span><br><span class="line">					Thread.sleep(<span class="number">60</span> * <span class="number">1000</span>); <span class="comment">// 为测试，占用了就不放</span></span><br><span class="line">				&#125;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">			e.printStackTrace();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="线程并发协作（生产者-消费者模式）"><a href="#线程并发协作（生产者-消费者模式）" class="headerlink" title="线程并发协作（生产者/消费者模式）"></a>线程并发协作（生产者/消费者模式）</h2><ul>
<li><strong>生产者</strong>：负责生产数据的模块（模块可能是方法、对象、线程、进程）</li>
<li><strong>消费者</strong>：负责处理数据的模块</li>
<li><strong>缓冲区</strong>：消费者不能直接使用生产者的数据，生产者将生产好的数据放入“缓冲区”，消费者从“缓冲区”拿取要处理的数据</li>
<li>缓冲区是实现并发的核心，缓冲区的设置的3个好处<ul>
<li><strong>实现线程的并发协作</strong>。有了缓冲区以后，生产者线程只需要往缓冲区里面放置数据，而不需要管消费者消费的情况；同样，消费者只需要从缓冲区拿数据处理即可，也不需要管生产者生产的情况。 这样，就从逻辑上实现了“生产者线程”和“消费者线程”的分离</li>
<li><strong>解耦了生产者和消费者</strong>。生产者不需要和消费者直接打交道</li>
<li><strong>解决忙闲不均，提高效率</strong>。生产者产生数据慢时，缓冲区任有数据，不影响消费者消费；消费者处理数据慢时，生产者然可以继续玩缓冲区里放置数据</li>
</ul>
</li>
<li><code>wait()</code>、<code>notify()</code>、<code>notifyAll()</code>均是<code>java.lang.Object</code>类的方法，只能在同步方法或同步代码中使用，否则会抛出异常</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestProduce</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        SyncStack sStack = <span class="keyword">new</span> SyncStack(); <span class="comment">// 定义缓冲区对象；</span></span><br><span class="line">        Producer producer = <span class="keyword">new</span> Producer(sStack); <span class="comment">// 定义生产线程；</span></span><br><span class="line">        Consumer consumer = <span class="keyword">new</span> Consumer(sStack); <span class="comment">// 定义消费线程；</span></span><br><span class="line">        producer.start();</span><br><span class="line">        consumer.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Mantou</span> </span>&#123;<span class="comment">// 馒头</span></span><br><span class="line">    <span class="keyword">int</span> id;</span><br><span class="line">    Mantou(<span class="keyword">int</span> id) &#123;</span><br><span class="line">        <span class="keyword">this</span>.id = id;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">SyncStack</span> </span>&#123;<span class="comment">// 缓冲区(相当于：馒头筐)</span></span><br><span class="line">    <span class="keyword">int</span> index = <span class="number">0</span>;</span><br><span class="line">    Mantou[] ms = <span class="keyword">new</span> Mantou[<span class="number">10</span>];</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title">push</span><span class="params">(Mantou m)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">while</span> (index == ms.length) &#123;<span class="comment">//说明馒头筐满了</span></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">               <span class="comment">//wait后，线程会将持有的锁释放，进入阻塞状态；</span></span><br><span class="line">               <span class="comment">//这样其它需要锁的线程就可以获得锁；</span></span><br><span class="line">                <span class="keyword">this</span>.wait();</span><br><span class="line">                <span class="comment">//这里的含义是执行此方法的线程暂停，进入阻塞状态，</span></span><br><span class="line">                <span class="comment">//等消费者消费了馒头后再生产。</span></span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 唤醒在当前对象等待池中等待的第一个线程。</span></span><br><span class="line">        <span class="comment">//notifyAll叫醒所有在当前对象等待池中等待的所有线程。</span></span><br><span class="line">        <span class="keyword">this</span>.notify();</span><br><span class="line">        <span class="comment">// 如果不唤醒的话。以后这两个线程都会进入等待线程，没有人唤醒。</span></span><br><span class="line">        ms[index] = m;</span><br><span class="line">        index++;</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> Mantou <span class="title">pop</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">while</span> (index == <span class="number">0</span>) &#123;<span class="comment">//如果馒头筐是空的；</span></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">//如果馒头筐是空的，就暂停此消费线程</span></span><br><span class="line">                <span class="keyword">this</span>.wait();   <span class="comment">//等生产线程生产完再来消费；</span></span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">this</span>.notify();</span><br><span class="line">        index--;</span><br><span class="line">        <span class="keyword">return</span> ms[index];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Producer</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;<span class="comment">// 生产者线程</span></span><br><span class="line">    SyncStack ss = <span class="keyword">null</span>;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Producer</span><span class="params">(SyncStack ss)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.ss = ss;</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">            System.out.println(<span class="string">"生产馒头："</span> + i);</span><br><span class="line">            Mantou m = <span class="keyword">new</span> Mantou(i);</span><br><span class="line">            ss.push(m);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Consumer</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;<span class="comment">// 消费者线程；</span></span><br><span class="line">    SyncStack ss = <span class="keyword">null</span>;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Consumer</span><span class="params">(SyncStack ss)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.ss = ss;</span><br><span class="line">    &#125;</span><br><span class="line"> </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; i++) &#123;</span><br><span class="line">            Mantou m = ss.pop();</span><br><span class="line">            System.out.println(<span class="string">"消费馒头："</span> + i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="任务定时调度"><a href="#任务定时调度" class="headerlink" title="任务定时调度"></a>任务定时调度</h2><ul>
<li><code>java.util.Timer</code>： 定时或每隔一定时间触发一次线程。Timer类本身是一个线程，只是它用来调用其它的线程</li>
<li><code>java.util.TimerTask</code>：TimerTask类是一个抽象类，实现了Runnable接口，具备多线程能力。</li>
<li>在实际使用时，一个Timer可以启动任意多个TimerTask实现的线程，但是多个线程之间会存在阻塞。所以如果多个线程之间需要完全独立的话，最好还是一个Timer启动一个TimerTask实现</li>
<li>可以使用开源框架quanz，更加方便的实现任务定时调度</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Timer;</span><br><span class="line"><span class="keyword">import</span> java.util.TimerTask;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestTimer</span></span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">		Timer t = <span class="keyword">new</span> Timer(); <span class="comment">// 定义计时器</span></span><br><span class="line">		MyTask task = <span class="keyword">new</span> MyTask(); <span class="comment">// 定义任务</span></span><br><span class="line">		t.schedule(task,<span class="number">3000</span>); <span class="comment">// 3秒后执行</span></span><br><span class="line">		<span class="comment">//t.schedule(task,5000,1000); // 5秒后每隔1秒执行一次</span></span><br><span class="line">		<span class="comment">//GregorianCalendar calendar = new GregorianCalendar(2019,11,14,20,28);</span></span><br><span class="line">		<span class="comment">//t.schedule(task,caldendar.getTime()); // 指定时间定时执行</span></span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyTask</span> <span class="keyword">extends</span> <span class="title">TimerTask</span></span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span></span>&#123;</span><br><span class="line">		<span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;<span class="number">10</span>;i++)&#123;</span><br><span class="line">			System.out.println(<span class="string">"任务："</span>+i);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong><em>参考《 Java核心技术 卷 I 》及互联网</em></strong></p>

      
    </div>

    

    
    
    

    

    
      
    
    

    

    <footer class="post-footer">
      
        
          
        
        <div class="post-tags">
          
            <a href="/tags/多线程/" rel="tag"># 多线程</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/11/03/时序图/" rel="next" title="时序图">
                <i class="fa fa-chevron-left"></i> 时序图
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>


  </div>


          </div>
          

  
    <div class="comments" id="gitalk-container">
    </div>

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/images/zhi.jpg" alt="小智">
            
              <p class="site-author-name" itemprop="name">小智</p>
              <div class="site-description motion-element" itemprop="description">Java,Linux,Mysql</div>
          </div>

          
            <nav class="site-state motion-element">
              
                <div class="site-state-item site-state-posts">
                
                  <a href="/archives/">
                
                    <span class="site-state-item-count">22</span>
                    <span class="site-state-item-name">日志</span>
                  </a>
                </div>
              

              
                
                
                <div class="site-state-item site-state-categories">
                  
                    
                      <a href="/categories/">
                    
                  
                    
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                    <span class="site-state-item-count">5</span>
                    <span class="site-state-item-name">分类</span>
                  </a>
                </div>
              

              
                
                
                <div class="site-state-item site-state-tags">
                  
                    
                      <a href="/tags/">
                    
                  
                    
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                    <span class="site-state-item-count">37</span>
                    <span class="site-state-item-name">标签</span>
                  </a>
                </div>
              
            </nav>
          

          

          

          

          

          
          

          
            
          
          

        </div>
      </div>

      
      <!--noindex-->
        <div class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
            
            
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#进程与线程的区别"><span class="nav-number">1.</span> <span class="nav-text">进程与线程的区别</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Java实现多线程的方法"><span class="nav-number">2.</span> <span class="nav-text">Java实现多线程的方法</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-继承Thread类"><span class="nav-number">2.1.</span> <span class="nav-text">1. 继承Thread类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-实现Runnable接口"><span class="nav-number">2.2.</span> <span class="nav-text">2. 实现Runnable接口</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#线程的状态"><span class="nav-number">3.</span> <span class="nav-text">线程的状态</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#终止线程的典型方式"><span class="nav-number">3.1.</span> <span class="nav-text">终止线程的典型方式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#暂停线程sleep-yield"><span class="nav-number">3.2.</span> <span class="nav-text">暂停线程sleep/yield</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#线程的联合-join"><span class="nav-number">3.3.</span> <span class="nav-text">线程的联合 join()</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#获取线程基本信息的方法"><span class="nav-number">4.</span> <span class="nav-text">获取线程基本信息的方法</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#线程的优先级"><span class="nav-number">5.</span> <span class="nav-text">线程的优先级</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#线程同步"><span class="nav-number">6.</span> <span class="nav-text">线程同步</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#线程不同步——银行取钱"><span class="nav-number">6.1.</span> <span class="nav-text">线程不同步——银行取钱</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#实现线程同步——银行取钱"><span class="nav-number">6.2.</span> <span class="nav-text">实现线程同步——银行取钱</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#死锁"><span class="nav-number">7.</span> <span class="nav-text">死锁</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#死锁问题"><span class="nav-number">7.1.</span> <span class="nav-text">死锁问题</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#解决死锁"><span class="nav-number">7.2.</span> <span class="nav-text">解决死锁</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#线程并发协作（生产者-消费者模式）"><span class="nav-number">8.</span> <span class="nav-text">线程并发协作（生产者/消费者模式）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#任务定时调度"><span class="nav-number">9.</span> <span class="nav-text">任务定时调度</span></a></li></ol></div>
            

          </div>
        </div>
      <!--/noindex-->
      

      

    </div>
  </aside>
  


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2019</span>
  <span class="with-love" id="animate">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">小智</span>

  

  
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    
      <span class="post-meta-item-text">站点阅读时长 &asymp;</span>
    
    <span title="站点阅读时长">2:07</span>
  
</div>









        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

  
    <span class="post-meta-item-icon">
      <i class="fa fa-user"></i>
    </span>
    <span class="site-uv" title="总访客量">
      <span class="busuanzi-value" id="busuanzi_value_site_uv"></span>
    </span>
  

  
    <span class="post-meta-divider">|</span>
  

  
    <span class="post-meta-item-icon">
      <i class="fa fa-eye"></i>
    </span>
    <span class="site-pv" title="总访问量">
      <span class="busuanzi-value" id="busuanzi_value_site_pv"></span>
    </span>
  
</div>









        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

    

    
  </div>

  

<script>
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>


























  
  <script src="/lib/jquery/index.js?v=3.4.1"></script>

  
  <script src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>


  


  <script src="/js/utils.js?v=7.1.2"></script>

  <script src="/js/motion.js?v=7.1.2"></script>



  
  


  <script src="/js/affix.js?v=7.1.2"></script>

  <script src="/js/schemes/pisces.js?v=7.1.2"></script>



  
  <script src="/js/scrollspy.js?v=7.1.2"></script>
<script src="/js/post-details.js?v=7.1.2"></script>



  


  <script src="/js/next-boot.js?v=7.1.2"></script>


  

  

  

  


  
    

<script src="//cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script>



<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.css">



<script src="//cdn.jsdelivr.net/npm/js-md5@0.7.3/src/md5.min.js"></script>

<script>
  var gitalk = new Gitalk({
    clientID: '4a3937b2ec1408fa593c',
    clientSecret: 'bb11519c1d0aafd8540c58fe182487d24b1a1a6f',
    repo: 'zengzhiLai.github.io',
    owner: 'zengzhiLai',
    admin: ['zengzhiLai'],
    id: md5(location.pathname),
    
      language: window.navigator.language || window.navigator.userLanguage,
    
    distractionFreeMode: 'true'
  });
  gitalk.render('gitalk-container');
</script>

  


  




  

  

  

  

  

  
  <script>
    (function(){
      var bp = document.createElement('script');
      var curProtocol = window.location.protocol.split(':')[0];
      bp.src = (curProtocol === 'https') ? 'https://zz.bdstatic.com/linksubmit/push.js' : 'http://push.zhanzhang.baidu.com/push.js';
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(bp, s);
    })();
  </script>


  

  

  

  

  

  

  

  

</body>
</html>
<!-- 页面点击小红心 -->
	<script type="text/javascript" src="js/schemes/clicklove.js"></script>